<?php
/**
 * Created by PhpStorm.
 * User: wodrow
 * Date: 17-5-25
 * Time: 下午5:32
 */

namespace common\components\gps;


use common\components\tools\Tools;
use common\models\CarGpsOrder;
use yii\base\ErrorException;
use yii\helpers\ArrayHelper;
use yii\httpclient\Client;

/**
 * Class Jimi
 * @package common\components\gps
 *
 * @property CarGpsOrder $order
 */
class Jimi extends Gps implements Api
{
    const PRE_SIGN = 868;
    const NAME = 'jimi';
    const NOTE = '几米'; // 图强 http://www.tuqiangol.com/index.jsp
    const VERSION = '1.0';
    const FORMAT = 'json';
    const SIGN_METHOD = 'md5';
    const AUTH_DURATION = 3600;
    const METHOD_ACCESSTOKEN = "jimi.oauth.token.get"; // 获取accesstoken
    const METHOD_REFRESH_TOKEN = 'jimi.oauth.token.refresh'; // 刷新access_token
    const METHOD_USER_CHILD_LIST = "jimi.user.child.list"; // 根据账户，获取该账户下的所有子账户信息。
    const METHOD_USER_DEV_LIST  = "jimi.user.device.list"; // 根据账户，获取该账户下所有IMEI信息
    const METHOD_USER_DEV_LOCATION = "jimi.user.device.location.list"; // 根据账户，获取该账户下所有IMEI的最新定位数据
//    const METHOD_USER_CREATE_CHILD = 'jimi.user.child.create'; // 为指定账号创建子账号
    const METHOD_USER_CREATE_CHILD = 'jimi.user.child.createPlatformUsers'; // 为指定账号创建子账号
    const METHOD_DEV_LOCATION = "jimi.device.location.get"; // 根据IMEI获取最新定位数据
    const METHOD_DEV_TRACK_LIST = "jimi.device.track.list"; // 根据IMEI获取轨迹数据
    const METHOD_DEV_BIND = "jimi.open.device.bind"; // 为设备IMEI绑定用户
    const METHOD_DEV_MOVE = "jimi.open.device.move"; // 为设备IMEI绑定用户
    const METHOD_DEV_UNBIND = "jimi.open.device.unbind"; // 为设备IMEI解除绑定用户
    const METHOD_DEV_UPDATE = "jimi.open.device.update"; // 为设备IMEI修改车辆信息
    const METHOD_DEV_LOCATION_MAP = 'jimi.open.device.location.map'; // 获取设备定位地图页面
    const METHOD_FENCE_CREATE = "jimi.open.device.fence.create"; // 为设备imei创建电子围栏
    const METHOD_FENCE_DELETE = "jimi.open.device.fence.delete"; // 为设备imei删除电子围栏
    const METHOD_LBS_GET = "jimi.lbs.address.get"; // wifi、基站定位解析
    const METHOD_PUSH_ALARM = "jimi.push.device.alarm"; // 推送设备告警信息

    const ACCOUNT_COMMON = 9; // 普通用户

    public $config;

    public function setConfig()
    {
        $this->config = [
            'app_key' => Config::$jimi['key'],
            'app_secret' => Config::$jimi['secret'],
            'user_id' => Config::$jimi['admin_user'],
            'password' => Config::$jimi['password'],
            'url' => Config::$jimi['url'],
        ];
    }

    /**
     * @param $data
     * @return mixed
     */
    public function configAndSend($data, $other_data = [])
    {
        $this->setConfig();
        $timestamp = date("Y-m-d H:i:s");
        $app_key = $this->config['app_key'];
        $app_secret = $this->config['app_secret'];
        $sign_method = self::SIGN_METHOD;
        $v = self::VERSION;
        $format = self::FORMAT;
        $data = array_merge($data, [
            'timestamp' => $timestamp,
            'app_key' => $app_key,
            'sign_method' => $sign_method,
            'v' => $v,
            'format' => $format,
        ]);
        ksort($data); // 排序
        $x = '';
        foreach ($data as $k => $v){
            $x .= $k.$v; // 拼接
        }
        $y = $app_secret.$x.$app_secret; // 前后加app secret
        $z = md5($y); // 加密
        $z = strtoupper($z);
        $sign = $z; // 转16进制
        $data['sign'] = $sign;
        $client = new Client();
        if (isset($other_data['no_send'])){
//            Tools::log($this->config['url']);
//            Tools::log($data);
            exit;
        }
        $request = $client->createRequest()->setMethod('post')->setUrl($this->config['url'])->setData($data);
        /*$_tmp = [];
        foreach ($data as $k => $v){
            $_tmp[] = $k."=".$v;
        }
        $_url = $this->config['url']."?".Tools::arr2str($_tmp, '&');
        var_dump($_url);*/
        $response = $request->send();
        $r = json_decode($response->content);
        /*foreach ($data as $k => $v){
            $a[] = $k."=".$v;
        }
        $b = implode('&', $a);
        $url = 'http://open.aichezaixian.com/route/rest'."?".$b;
        var_dump($url);
        var_dump($r);exit;*/
        return $r;
    }

    public function getAccessToken()
    {
        $user_id = $this->config['user_id'];
        $user_pwd_md5 = md5($this->config['password']);
        $expires_in = self::AUTH_DURATION;
        if (\Yii::$app->cache->get($user_id.$user_pwd_md5)){
            $accesstoken = \Yii::$app->cache->get($user_id.$user_pwd_md5);
        }else{
            $data = [
                'method' => self::METHOD_ACCESSTOKEN,
                'user_id' => $user_id,
                'user_pwd_md5' => $user_pwd_md5,
                'expires_in' => $expires_in,
            ];
            $r = $this->configAndSend($data);
            if (!isset($r->code)){
                throw new ErrorException("获取access_token/code错误 ".var_export($r, true));
            }
            if ($r->code==0){
                $accesstoken = $r->result->accessToken;
            }else{
                throw new ErrorException("获取access_token错误 ".var_export($data, true).var_export($r, true));
            }
            $b = \Yii::$app->cache->set($user_id.$user_pwd_md5, $accesstoken, $expires_in);
        }
        return $accesstoken;
    }

    // 根据账户，获取该账户下的所有子账户信息
    public function getUserChildList($target = null)
    {
        $target = $target?$target:$this->config['user_id'];
        $accessToken = $this->getAccessToken();
        $data = [
            'method' => self::METHOD_USER_CHILD_LIST,
            'access_token' => $accessToken,
            'target' => $target,
        ];
        $r = $this->configAndSend($data);
        return $r;
    }

    public function createUserChild($data)
    {
        $accessToken = $this->getAccessToken();
        $_data = [
            'method' => self::METHOD_USER_CREATE_CHILD,
            'access_token' => $accessToken,
            'account_type' => self::ACCOUNT_COMMON,
            'top_account' => $data['top_account'],
            'nick_name' => $data['nick_name'],
            'account' => $data['account'],
            'password' => $data['password'],
        ];
        $r = $this->configAndSend($_data);
        return $r;
    }

    public function checkHasUser($client_name)
    {
        $r = $this->getUserChildList();
        if (!isset($r->result)){
            throw new ErrorException("getUserChildList: ".var_export($r, true));
        }
        $accounts = $names = [];
        foreach (Tools::objectToArray($r->result) as $k => $v){
            $accounts[] = $v['account'];
            $names[] = $v['name'];
        }
        if (in_array($client_name, $accounts)){
            $x = 1;
        }else{
            $x = 0;
        }
        return $x;
    }

    // 根据账户，获取该账户下所有IMEI信息
    public function getUserDevList()
    {
        $accessToken = $this->getAccessToken();
        $data = [
            'method' => self::METHOD_USER_DEV_LIST,
            'access_token' => $accessToken,
            'target' => "易商新程",
        ];
        $r = $this->configAndSend($data);
        return $r;
    }

    // 获取该账户下所有IMEI的最新定位数据
    public function getUserDevLocation()
    {
        $accessToken = $this->getAccessToken();
        $data = [
            'method' => self::METHOD_USER_DEV_LOCATION,
            'access_token' => $accessToken,
            'target' => "易商新程",
        ];
        $r = $this->configAndSend($data);
        return $r;
    }

    /**
     * 获取单个或多个设备最新的位置信息
     * @param $imeis
     * @param $map_type
     * @return mixed
     */
    public function getDevLocation($imeis, $map_type=null)
    {
        $accessToken = $this->getAccessToken();
//        $imeis = $imeis; // 设备imei号，多个中间用英文逗号隔开； 如果设备过多，建议采用POST方式(一次最多100个IMEI)
//        $map_type = $map_type; // 如果要显示在百度地图上，map_type=BAIDU此时返回的经纬度将经过baidu校准方式校准 如果要显示在google地图上，map_type=GOOGLE，此时返回的经纬度将经过google校准方式校准 map_type如果不填，则返回原始经纬度
        $data = [
            'method' => self::METHOD_DEV_LOCATION,
            'access_token' => $accessToken,
            'imeis' => $imeis,
        ];
        if ($map_type){
            $data['map_type'] = $map_type;
        }else{
            $data['map_type'] = 'BAIDU';
        }
        $r = $this->configAndSend($data);
        return $r;
    }

    /**
     * 7.13为设备IMEI绑定用户
     * @param $imei
     * @param $user_id 绑定的用户账号，必须是终端账号
     * @return mixed
     */
    public function devBind($imei, $user_id)
    {
        $accessToken = $this->getAccessToken();
        $data = [
            'method' => self::METHOD_DEV_BIND,
            'access_token' => $accessToken,
//            'imei' => $imei,
//            'user_id' => $user_id,
            'imei' => '868120167412383',
            'user_id' => '13758138832',
        ];
        $r = $this->configAndSend($data);
        return $r;
    }

    /**
     * 转移设备
     * @desc 将账号上的设备转移到下级账号上。
     * @param $src_account 原用户账号
     * @param $dest_account 目标用户账号（必须是原账号的下级）
     * @param $imeis 设备imei列表，使用逗号分隔，最多支持500个
     */
    public function moveDevice($src_account, $dest_account, $imeis)
    {
        $accessToken = $this->getAccessToken();
        $data = [
            'method' => self::METHOD_DEV_MOVE,
            'access_token' => $accessToken,
            'src_account' => $src_account,
            'dest_account' => $dest_account,
            'imeis' => $imeis,
        ];
        $r = $this->configAndSend($data);
        return $r;
    }

    /**
     * 为设备IMEI修改车辆信息
     * @param $data
     * @return mixed
     */
    public function devUpdate($data)
    {
        $data = array_merge([
            'method' => self::METHOD_DEV_UPDATE,
            'access_token' => $this->accessToken,
        ], $data);
//        var_export($data);exit;
        $r = $this->configAndSend($data);
        return $r;
    }

    /**
     * 获取设备定位地图页面
     */
    public function getLocationMap($data)
    {
        $data = array_merge([
            'method' => self::METHOD_DEV_LOCATION_MAP,
            'access_token' => $this->accessToken,
        ], $data);
//        var_export($data);exit;
        $r = $this->configAndSend($data);
        return $r;
    }

    public function beforeAddGps()
    {

    }

    public function setPassword($password = '888888')
    {
        return md5($password);
    }

    public function addGps()
    {
        $this->beforeAddGps();
        $this->setConfig();
        $_data = unserialize($this->order->data);
        $r = $this->checkHasUser($_data['client_name']);
        if (!$r){
            if (isset($_data['jimi_user_config'])){
                $user_conf = $_data['jimi_user_config'];
            }else{
                $user_conf = [
                    'top_account' => $this->config['user_id'],
                    'nick_name' => $_data['client_name'],
                    'account' => $_data['client_name'],
//                    'password' => md5($_data['client_manager_mobile']),
//                    'password' => md5('888888'),
                    'password' => $this->setPassword(),
                ];
            }
            $r = $this->createUserChild($user_conf);
            if (isset($r->code)&&$r->code==0){}else{
                throw new ErrorException($r->message, "500".$r->code);
            }
        }
//        $r = $this->moveDevice($this->config['user_id'], '杭州测试业务部', '868120167412383');
        $r = $this->moveDevice($this->config['user_id'], $_data['client_name'], $this->order->gps_serial_number);
        if (property_exists($r, 'code')&&$r->code==0){}else{
            throw new ErrorException(var_export($r, true), 1075);
//            throw new ErrorException('失败', 1075);
//            return [
//                'platform_back' => $r,
//                '_back' => Tools::objectToArray($r),
//            ];
        }
        /*$x = [
            'client_name' => 'test3', // 网点名称
            'client_manager_mobile' => '17091551612',
            'custom_name' => 'test3',
            'plate_number' => '浙DX914U',
            'custom_mobile' => '17091551612',
        ];*/
        $data = [
            'imei' => $this->order->gps_serial_number,
        ];
        if ($_data['custom_name'])$data['device_name']=$_data['custom_name'];
        if ($_data['plate_number'])$data['vehicle_number']=$_data['plate_number'];
        if ($_data['custom_name'])$data['driver_name']=$_data['custom_name'];
        if ($_data['custom_mobile'])$data['driver_phone']=$_data['custom_mobile'];
//        $data = array_filter($data);
        $r = $this->devUpdate($data);
        if ($r->code==0){
            $_x = Tools::objectToArray($r);
            return [
                'platform_back' => $r,
                '_back' => Tools::objectToArray($r),
                'other_data' => [
                    'success' => true,
                    'msg' => $_x['message'],
                ],
            ];
        }else{
            throw new ErrorException(var_export($r, true), 1074);
        }
    }

    public function updateGpsCarInfo()
    {
        $_data = unserialize($this->order->data);
        /*$x = [
            'client_name' => 'test3', // 网点名称
            'client_manager_mobile' => '17091551612',
            'custom_name' => 'test3',
            'plate_number' => '浙DX914U',
            'custom_mobile' => '17091551612',
        ];*/
        $data = [
            'imei' => $this->order->gps_serial_number,
//            'device_name' => $this->order->dev_name,
//            'vehicle_name' => $this->order->car_name,
//            'vehicle_icon' => $this->order->car_icon,
            'vehicle_number' => $_data['plate_number'],
//            'vehicle_models' => $this->order->car_brand,
//            'driver_name' => $this->order->driver_name,
//            'driver_phone' => $this->order->driver_mobile,
        ];
        $data = array_filter($data);
    }

    public function getGps()
    {
        $this->setConfig();
        $this->checkOrder();
        $order = $this->order;
        $imeis = $order->gps_serial_number;
        $r = $this->getDevLocation($imeis);
        $other_data = [
            'gps_status' => '未上线',
        ];
        $other_data['gps_detail'] = [
            'doc-url' => "http://www.jimicloud.com/apiJimi.html#moveDevice",
            'imei' => "设备IMEI",
            'device_info' => "设备名称",
            'icon' => "车辆图标",
            'status' => "设备状态 0,离线; 1,在线",
            'lat' => "经度 (如果设备过期，值为0)",
            'lng' => "纬度 (如果设备过期，值为0)",
            'expireFlag' => "是否过期 1-未过期 0-过期",
            'activationFlag' => "是否激活 1-激活 0-未激活",
            'posType' => "卫星定位-GPS, 基站定位-LBS, WIFI定位-WIFI, 蓝牙定位-BEACON",
            'locDesc' => "位置信息",
            'gpsTime' => "GPS定位时间",
            'hbTime' => "心跳时间 UTC秒数(如果设备过期，值为0)",
            'speed' => "速度",
            'electQuantity' => "设备电量（0-100），部分设备型号不支持",
            'powerValue' => "外电电压（0-100），部分设备支持",
            '上线判断' => 'activationFlag==1',
        ];
        if ($r->code==0){
            $r_arr = Tools::objectToArray($r->result);
            if (/*$r_arr[0]['status'] == */1){
                if (isset($r_arr[0]['activationFlag'])&&$r_arr[0]['activationFlag']){
                    $other_data['gps_status'] = '已上线';
                    $other_data['gps_online_time'] = strtotime($r_arr[0]['gpsTime']);
                }
            }
        }
        return [
            'platform_back' => $r,
            'order' => $order,
            'other_data' => $other_data,
        ];
    }

    public function getGpsLocationData()
    {
        $this->setConfig();
        $imei = $this->order->gps_serial_number;
        $x= $this->getLocationMap(['imei'=>$imei]);
        $data = [];
        if ($x->code == 0){
            $data['html'] = $x->result;
        }else{
            throw new ErrorException($x->message);
        }
        return $data;
    }
}